﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Windows.Automation;
using System.Threading;

namespace AutomationFrameworkDemo
{
    public partial class AutomationTesterForm : Form
    {
        private Process myApplicationProcess;
        private AutomationElement myAutomationElement;
        private AutomationElement myMeasurementControl;
        private AutomationElement myTreeControl;

        public AutomationTesterForm()
        {
            InitializeComponent();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            CloseDemoApp();
            base.OnClosing(e);
        }

        private void myButtonFindDemoApp_Click(object sender, EventArgs e)
        {
            // InProc
            //string path = Application.StartupPath;
            //path = Directory.GetParent(path).ToString();
            //path = Directory.GetParent(path).ToString();
            //path = Directory.GetParent(path).ToString();
            //path = Path.Combine(path, @"bin\Debug\AutomationProviderDemo.exe");
            //Process.Start(path);

            // Separate Process
            myApplicationProcess = Process.GetProcessesByName("TreeControlTester")[0];

            AutomationElement aeDesktop = AutomationElement.RootElement;

            // a better approach
            AutomationElement aeForm = null;
            int numWaits = 0;
            do
            {
                Console.WriteLine("Looking for TreeControlTester . . . ");
                aeForm = aeDesktop.FindFirst(TreeScope.Children,
                    new PropertyCondition(
                        AutomationElement.NameProperty,
                        "TreeControl Tester Form"));

                ++numWaits;
                Thread.Sleep(100);
            }

            while (aeForm == null && numWaits < 50);


            if (aeForm == null)
            {
                WriteInLog("Please run the Demo Application before running the Tester.");
            }
            else
            {
                AutomationElement aeButton = aeForm.FindFirst(TreeScope.Children,
                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

                Thread.Sleep(1000);

                if (aeButton != null)
                {
                    InvokePattern ipClickButton1 = (InvokePattern)aeButton.GetCurrentPattern(InvokePattern.Pattern);

                    ipClickButton1.Invoke();
                }

                myTreeControl = aeForm.FindFirst(TreeScope.Children,
                    new PropertyCondition(AutomationElement.ClassNameProperty, "Tree"));

                myMeasurementControl = aeForm.FindFirst(TreeScope.Children,
                                    new PropertyCondition(AutomationElement.ClassNameProperty, "MeasurementControl"));

                myAutomationElement = myMeasurementControl;

                if (myAutomationElement != null)
                {

                    EnableButtons(true);
                    myButtonFindDemoApp.Enabled = false;

                    object obj = null;
                    if (myAutomationElement.TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out obj))
                    {
                        ExpandCollapsePattern ep = (ExpandCollapsePattern)obj;
                        WriteInLog("Header State: " + ep.Current.ExpandCollapseState.ToString());

                        WriteInLog("Changing Header State to - Expanded (thru automation)");
                        MessageBox.Show("Expanding the Control", "Automation Test");
                        ep.Expand();

                        WriteInLog("Header State: " + ep.Current.ExpandCollapseState.ToString());
                    }

                    AutomationElement ele = TreeWalker.ControlViewWalker.GetFirstChild(myAutomationElement);
                    WriteInLog("Get First Child: " + ele.Current.Name);

                    AutomationElement next = TreeWalker.ControlViewWalker.GetNextSibling(ele);
                    WriteInLog("Get Next Child: " + next.Current.Name);

                    AutomationElement last = TreeWalker.ControlViewWalker.GetLastChild(myAutomationElement);
                    WriteInLog("Get Last Child: " + last.Current.Name);

                    AutomationElement prev = TreeWalker.ControlViewWalker.GetPreviousSibling(last);
                    WriteInLog("Get Previous Child: " + prev.Current.Name);
                    obj = null;
                    if (last.TryGetCurrentPattern(ValuePattern.Pattern, out obj))
                    {
                        MessageBox.Show("Get the Value of Last Child (Thru ValuePattern).", "Automation Test");
                        ValuePattern pattern = (ValuePattern)obj;
                        MessageBox.Show("Last Child Name: " + pattern.Current.Value, "Automation Test");

                        MessageBox.Show("Setting its value to 'Updated Node'");
                        pattern.SetValue("Updated Node");
                    }
                }
            }
        }

        private void EnableButtons(bool enable)
        {
            myButtonGetBoundingRect.Enabled = enable;
            myButtonGetCurrentValue.Enabled = enable;
            myButtonClickOnRootItem.Enabled = enable;
            myButtonToggleEnabledState.Enabled = enable;
            myButtonGetExpandState.Enabled = enable;
            myGroupBoxSelectExpandState.Enabled = enable;
            myGroupBoxSelectControl.Enabled = enable;
            myButtonGetChildBoundingRect.Enabled = enable;
            myButtonKillApplication.Enabled = enable;
        }

        private void myButtonKillApplication_Click(object sender, EventArgs e)
        {
            CloseDemoApp();
        }

        private void CloseDemoApp()
        {
            if (myApplicationProcess != null)
            {
                if (!myApplicationProcess.HasExited)
                {
                    myApplicationProcess.Kill();
                }
            }
            EnableButtons(false);
            myButtonFindDemoApp.Enabled = true;
            richTextBox1.Clear();
        }

        private void myButtonGetBoundingRect_Click(object sender, EventArgs e)
        {
            WriteInLog("Control's Bounding Rectangle: " + myAutomationElement.Current.BoundingRectangle.ToString());
        }

        private void myButtonGetCurrentValue_Click(object sender, EventArgs e)
        {
            object pattern = null;
            if (myAutomationElement.TryGetCurrentPattern(ValuePattern.Pattern, out pattern))
            {
                ValuePattern valuePattern = (ValuePattern)pattern;
                WriteInLog(valuePattern.Current.Value);
            }
            else
            {
                WriteInLog("ValuePattern not supported by element");
            }
        }

        private void myButtonGetChildBoundingRect_Click(object sender, EventArgs e)
        {
            AutomationElementCollection controls = myAutomationElement.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom));

            foreach (AutomationElement aItem in controls)
            {
                WriteInLog("Name of Element: " + aItem.Current.Name + ", Bounding Rectangle: " + aItem.Current.BoundingRectangle.ToString());
            }
        }

        private void myRadioButtonCollapse_CheckedChanged(object sender, EventArgs e)
        {
            object pattern = null;
            if (myAutomationElement.TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out pattern))
            {
                ExpandCollapsePattern expandPattern = (ExpandCollapsePattern)pattern;
                if (myRadioButtonCollapse.Checked)
                {
                    expandPattern.Collapse();
                }
                else
                {
                    expandPattern.Expand();
                }
            }
            else
            {
                WriteInLog("ExpandCollapsePattern not supported by element");
            }
        }

        private void myButtonGetExpandState_Click(object sender, EventArgs e)
        {
            object pattern = null;
            if (myAutomationElement.TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out pattern))
            {
                ExpandCollapsePattern expandPattern = (ExpandCollapsePattern)pattern;
                WriteInLog(expandPattern.Current.ExpandCollapseState.ToString());
            }
            else
            {
                WriteInLog("ExpandCollapsePattern not supported by element");
            }
        }

        private void WriteInLog(string text)
        {
            richTextBox1.AppendText(text);
            richTextBox1.AppendText("\r\n");
            richTextBox1.ScrollToCaret();
        }

        private void myRadioButtonControl_CheckedChanged(object sender, EventArgs e)
        {
            if (myRadioButtonMeasControl.Checked)
            {
                myAutomationElement = myMeasurementControl;
            }
            else
            {
                myAutomationElement = myTreeControl;
            }
        }

        private void myButtonClickOnRootItem_Click(object sender, EventArgs e)
        {
            object pattern = null;
            if (myAutomationElement.TryGetCurrentPattern(InvokePattern.Pattern, out pattern))
            {
                InvokePattern invokePattern = (InvokePattern)pattern;
                invokePattern.Invoke();
                WriteInLog("Executed InvokePattern.Invoke()");
            }
            else
            {
                WriteInLog("IInvokePattern not supported by element");
            }
        }

        private void myButtonToggleEnabledState_Click(object sender, EventArgs e)
        {
            object pattern = null;
            if (myAutomationElement.TryGetCurrentPattern(TogglePattern.Pattern, out pattern))
            {
                TogglePattern togglePattern = (TogglePattern)pattern;
                WriteInLog("Before Toggleing, Enabled State:" + togglePattern.Current.ToggleState.ToString());
                togglePattern.Toggle();
                WriteInLog("After Toggleing, Enabled State:" + togglePattern.Current.ToggleState.ToString());
            }
            else
            {
                WriteInLog("ITogglePattern not supported by element");
            }            
        }
    }
}
